package client

import (
  "encoding/json"
  "net/http"
  "log"
  "time"
  "sync"
  "github.com/gorilla/websocket"

  "xszGame/common/models"
  "xszGame/app/qianji"
  "xszGame/app/laohuji"
)
var upgrader = websocket.Upgrader{
  CheckOrigin: func(r *http.Request) bool {
    return true // 允许跨域连接
  },
}

var (
  activeConns    = make(map[*websocket.Conn]struct{}) // 存储所有活跃连接
  connByToken    = make(map[string]*websocket.Conn)   // 新增：Token -> Conn 映射
	tokenByConn    = make(map[*websocket.Conn]string)   // Conn -> OpenID（Token）
  connMutex      sync.RWMutex                         // 并发保护
)

func WebSocketHandler(w http.ResponseWriter, r *http.Request) {
  conn, err := upgrader.Upgrade(w, r, nil)
  if err != nil {
    log.Println("WebSocket 升级失败:", err)
    return
  }
  
	// 延迟关闭连接和清理映射
	defer func() {
		connMutex.Lock()
		if token, ok := tokenByConn[conn]; ok {
			delete(connByToken, token)
			delete(tokenByConn, conn)
			log.Printf("连接关闭，清除 token=%s 映射", token)
		}
		connMutex.Unlock()
		conn.Close()
	}()

  for {
    _, msg, err := conn.ReadMessage()
    if err != nil {
      if websocket.IsUnexpectedCloseError(err,
        // 常量1001 对方离开  客户端或服务器正在 关闭或刷新页面，因此中断连接。
        websocket.CloseGoingAway,
        // 常量1006 异常关闭  连接意外断开，未发送正常的关闭帧（比如崩溃或网络问题）
        websocket.CloseAbnormalClosure,
        // 常量1000 正常关闭  通信双方都正常完成了任务，主动关闭连接。
        websocket.CloseNormalClosure) {
        log.Printf("WebSocket 异常断开: %v", err)
      } else {
        log.Printf("WebSocket 正常断开: %v", err)
      }
      break
    }

    var msgFmt client.ClientMsg
    err = json.Unmarshal(msg, &msgFmt)
    if err != nil {
      log.Println("JSON解析错误:", err)
    } else {
      log.Printf("收到消息: %+v\n", msgFmt)
    }

    // 用户绑定（DataType == 102）
    if msgFmt.DataType == 102 {
      var bandMsg client.BandMsg
      bandMsg.DataType = 102
      if msgFmt.OpenID == "" {
        bandMsg.Status = 2
        bandMsg.Data = "用户绑定失败缺少openId"
        if err := conn.WriteJSON(bandMsg); err != nil {
          log.Println("WriteJSON系统错误:", err)
          return
        }
        return
      }
      // 用户绑定
      connMutex.Lock()
      connByToken[msgFmt.OpenID] = conn
      tokenByConn[conn] = msgFmt.OpenID
      connMutex.Unlock()
      // 发送消息
      bandMsg.OpenID = msgFmt.OpenID
      bandMsg.Status = 1
      bandMsg.Data = "用户绑定成功"
      if err := conn.WriteJSON(bandMsg); err != nil {
        log.Println("WriteJSON系统错误:", err)
      }
      return
    }

    // 处理心跳消息（DataType=101
    if msgFmt.DataType == 101 {
      // 发送 PONG
      var pongMsg client.PongMsg
        pongMsg.DataType = 101
        pongMsg.Time = time.Now().UnixMilli()
        pongMsg.Status = 1
      if err := conn.WriteJSON(pongMsg); err != nil {
        log.Println("发送 PONG 失败:", err)
        return
      }
      continue
    }

    // 用户解绑/退出（DataType == 104）
    if msgFmt.DataType == 104 {
      if msgFmt.OpenID != "" {
        connMutex.Lock()
        // 防止误删其他连接：只有当前连接才删除映射
        if oldConn, ok := connByToken[msgFmt.OpenID]; ok && oldConn == conn {
          delete(connByToken, msgFmt.OpenID)
        }
        delete(tokenByConn, conn)
        connMutex.Unlock()
        log.Printf("用户解绑成功: %s", msgFmt.OpenID)
      } else {
        log.Println("用户解绑失败: 缺少 OpenID")
        return
      }
    }
    // 游戏上下文
    ctx := client.GameContext{
      Conn: conn,                  // 存入链接
      Msg: msgFmt,                 // 存入消息
      PlayerID: tokenByConn[conn], // 存入当前玩家
    }

    // 根据游戏类型分发处理
    switch msgFmt.Type {
    // 千机牌
    case 1:
      qianji.Handle(&ctx)
    // 老虎机
    case 2:
      laohuji.Handle(&ctx)
    default:
      log.Println("参数错误，未知游戏类型:", msgFmt.Type)
    }
  }
}
